/**  
 * All rights Reserved, Designed By Suixingpay.
 * @author: chenfeifei[chen_ff@suixingpay.com] 
 * @date: 2017年7月20日 下午9:00:55   
 * @Copyright ©2017 Suixingpay. All rights reserved. 
 * 注意：本内容仅限于随行付支付有限公司内部传阅，禁止外泄以及用于其他的商业用途。
 */
package cn.hennancf.qieqie.utils;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**  
 * AttributeUtils 根据前台需要属性传值(去除对象多余的属性)
 * @author: chenfeifei[chen_ff@suixingpay.com]
 * @date: 2017年7月20日 下午9:00:55
 * @version: V1.0
 * @review: chenfeifei[chen_ff@suixingpay.com]/2017年7月20日 下午9:00:55
 */
public class AttributeUtils {
    private final static Logger LOGGER = LoggerFactory.getLogger(AttributeUtils.class);
    private final static String PRE = "get";
    
    
    /**   
     * getAttributes 获取一个对象的部分属性
     * @param t:需要提取的属性的对象
     * @param list:需要提取对象的特定属性的list
     * @return map<attribute, getAttribute>
     * @throws IllegalAccessException
     * @throws IllegalArgumentException
     * @throws InvocationTargetException 
     */  
    public static <T> Map<String, Object> getAttributes(T t, String... attributes) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        LOGGER.info("---获取对象特定操作----所需参数=[{}], 对象=[{}]", attributes, t);
        
        Map<String, Object> map = new HashMap<>();
        Class<? extends Object> clazz = t.getClass();
        Method [] methods = clazz.getMethods();
        List<String> methodNames = getMethodName(attributes);//根据属性值生成对应的get方法
        
        for (Method method : methods) {
            if (methodNames.contains(method.getName())) {//遍历方法提取参数中的属性对应的get方法
                String key = StringUtils.removeStart(method.getName(), PRE);
                key =  key.substring(0, 1).toLowerCase() + key.substring(1);
                Object value = method.invoke(t);
                map.put(key, value);
            }
        }
        
        LOGGER.info("---获取对象特定操作----返回值map=[{}]", map);
        return map;
    }
    
    /**   
     * 根据属性值生成对应的get方法的methodName
     * @param list 属性
     * @return 
     */  
    private static List<String> getMethodName(String... attributes){
        List<String>methodList = new LinkedList<>();
        for (String str : attributes) {
            str =  str.substring(0, 1).toUpperCase() + str.substring(1);
            methodList.add(PRE + str);
        }
        return methodList;
    }
    
    /**   
     * 判断两个对象的相应属性是否相同
     * @param t1 对象1
     * @param t2 对象2
     * @param attributes 属性名
     * @return
     * @throws IllegalAccessException
     * @throws IllegalArgumentException
     * @throws InvocationTargetException 
     */  
    public static <T> boolean equals(T t1, T t2, String... attributes) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException{
        LOGGER.info("-----判断两个对象的相应属性是否相同----");
        
        Class<? extends Object> clazz = t1.getClass();
        if (!clazz.equals(t2.getClass())) return false;//是否属于同一类
        Method [] methods = clazz.getMethods();
        List<String> methodNames = getMethodName(attributes);//根据属性值生成对应的get方法
        
        for (Method method : methods) {
            if (methodNames.contains(method.getName())) {//遍历方法提取参数中的属性对应的get方法
                if (method.invoke(t1) == null && method.invoke(t2) == null) continue;//判断两个属性同时为null
                
                if (!method.invoke(t1).equals(method.invoke(t2))) {
                    LOGGER.info("-----两对象相应属性相同----t1 = [{}], t2 = [{}]", t1, t2);
                    return false;   
                }
            }
        }
        
        LOGGER.info("-----两对象相应属性相同----");
        return true;
    }
    
    /**   
     * 判断两个对象的所有属性是否相同
     * @param t1 对象1
     * @param t2 对象2
     * @param attributes 属性名
     * @return
     * @throws IllegalAccessException
     * @throws IllegalArgumentException
     * @throws InvocationTargetException 
     */  
    public static <T> boolean equals(T t1, T t2) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException{
        LOGGER.info("-----判断两个对象的相应属性是否相同----");
        
        Class<? extends Object> clazz = t1.getClass();
        if (!clazz.equals(t2.getClass())) return false;//是否属于同一类
        Method [] methods = clazz.getMethods();
        
        for (Method method : methods) {
            if (!StringUtils.startsWith(method.getName(), PRE)) continue;//判断是否是get方法
            if (method.invoke(t1) == null && method.invoke(t2) == null) continue;//判断两个属性同时为null
            if (!method.invoke(t1).equals(method.invoke(t2))) {
                LOGGER.info("-----两对象相应属性相同----t1 = [{}], t2 = [{}]", t1, t2);
                return false;   
            }
        }
        
        LOGGER.info("-----两对象相应属性相同----");
        return true;
    }

    
//      public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
//      FrcsBlackListPo black =new FrcsBlackListPo();
//      FrcsBlackListPo black2 =new FrcsBlackListPo();
//      black.setBlackContent("测试");
//      black.setBlackSts("00");
//      black2.setBlackContent("测试");
//      System.out.println(equals(black,black2));
//  }
}
